#include "scene_manager.h"
#include "control/control_api.h"
#include "logger.h"
#include <stdlib.h>
#include <string.h>
#include <fnmatch.h>

// 场景执行上下文
typedef struct {
    scene_t *scene;
    scene_manager_t *manager;
    char *trigger_source;
    trigger_mode_t trigger_mode;
} scene_execution_context_t;

// 解析生效时间配置
static int parse_effective_time(json_t *json, effective_time_t *effective_time) {
    if (!json || !json_is_object(json) || !effective_time) {
        return ERROR_INVALID_PARAM;
    }

    memset(effective_time, 0, sizeof(effective_time_t));

    json_t *start_time = json_object_get(json, "start_time");
    if (start_time && json_is_string(start_time)) {
        effective_time->start_time = strdup(json_string_value(start_time));
    }

    json_t *end_time = json_object_get(json, "end_time");
    if (end_time && json_is_string(end_time)) {
        effective_time->end_time = strdup(json_string_value(end_time));
    }

    json_t *weekdays = json_object_get(json, "weekdays");
    if (weekdays && json_is_array(weekdays)) {
        size_t count = json_array_size(weekdays);
        effective_time->weekdays = malloc(count * sizeof(int));
        if (effective_time->weekdays) {
            effective_time->weekday_count = 0;
            for (size_t i = 0; i < count; i++) {
                json_t *weekday = json_array_get(weekdays, i);
                if (weekday && json_is_integer(weekday)) {
                    effective_time->weekdays[effective_time->weekday_count++] = json_integer_value(weekday);
                }
            }
        }
    }

    return SUCCESS;
}

// 释放生效时间配置
static void free_effective_time(effective_time_t *effective_time) {
    if (!effective_time) {
        return;
    }

    if (effective_time->start_time) free(effective_time->start_time);
    if (effective_time->end_time) free(effective_time->end_time);
    if (effective_time->weekdays) free(effective_time->weekdays);

    memset(effective_time, 0, sizeof(effective_time_t));
}

// 检查是否在生效时间内
bool scene_manager_check_effective_time(scene_t *scene) {
    if (!scene || !scene->time_management) {
        return true; // 未启用时间管理，始终生效
    }

    time_t now = time(NULL);
    struct tm *tm_now = localtime(&now);
    int current_minutes = tm_now->tm_hour * 60 + tm_now->tm_min;
    int current_weekday = tm_now->tm_wday + 1; // tm_wday: 0=Sunday, 1=Monday, ...

    // 检查星期
    bool weekday_match = false;
    for (size_t i = 0; i < scene->effective_time.weekday_count; i++) {
        if (scene->effective_time.weekdays[i] == current_weekday) {
            weekday_match = true;
            break;
        }
    }

    if (!weekday_match) {
        return false;
    }

    // 解析开始时间和结束时间
    int start_minutes = 0, end_minutes = 24 * 60;

    if (scene->effective_time.start_time) {
        int hour, minute;
        if (sscanf(scene->effective_time.start_time, "%d:%d", &hour, &minute) == 2) {
            start_minutes = hour * 60 + minute;
        }
    }

    if (scene->effective_time.end_time) {
        int hour, minute;
        if (sscanf(scene->effective_time.end_time, "%d:%d", &hour, &minute) == 2) {
            end_minutes = hour * 60 + minute;
        }
    }

    // 检查时间范围
    return (current_minutes >= start_minutes && current_minutes <= end_minutes);
}

// 值条件检查函数
static bool check_value_condition(json_t *actual_value, json_t *condition) {
    if (!actual_value || !condition || !json_is_object(condition)) {
        return false;
    }

    const char *operator_str = json_string_value(json_object_get(condition, "operator"));
    json_t *target_value = json_object_get(condition, "target_value");
    const char *value_type = json_string_value(json_object_get(condition, "value_type"));

    if (!operator_str || !target_value || !value_type) {
        return false;
    }

    // 根据值类型进行检查
    if (strcmp(value_type, "int") == 0) {
        if (!json_is_integer(actual_value) || !json_is_integer(target_value)) {
            return false;
        }

        int64_t actual = json_integer_value(actual_value);
        int64_t target = json_integer_value(target_value);

        if (strcmp(operator_str, "EQ") == 0) return actual == target;
        if (strcmp(operator_str, "NE") == 0) return actual != target;
        if (strcmp(operator_str, "GT") == 0) return actual > target;
        if (strcmp(operator_str, "GE") == 0) return actual >= target;
        if (strcmp(operator_str, "LT") == 0) return actual < target;
        if (strcmp(operator_str, "LE") == 0) return actual <= target;
    }
    else if (strcmp(value_type, "float") == 0) {
        if ((!json_is_real(actual_value) && !json_is_integer(actual_value)) ||
            (!json_is_real(target_value) && !json_is_integer(target_value))) {
            return false;
        }

        double actual = json_is_real(actual_value) ? json_real_value(actual_value) :
                            json_is_integer(actual_value) ? (double)json_integer_value(actual_value) : 0.0;
        double target = json_is_real(target_value) ? json_real_value(target_value) :
                            json_is_integer(target_value) ? (double)json_integer_value(target_value) : 0.0;

        if (strcmp(operator_str, "EQ") == 0) return fabs(actual - target) < 1e-9;
        if (strcmp(operator_str, "NE") == 0) return fabs(actual - target) >= 1e-9;
        if (strcmp(operator_str, "GT") == 0) return actual > target;
        if (strcmp(operator_str, "GE") == 0) return actual >= target;
        if (strcmp(operator_str, "LT") == 0) return actual < target;
        if (strcmp(operator_str, "LE") == 0) return actual <= target;
    }
    else if (strcmp(value_type, "string") == 0) {
        if (!json_is_string(actual_value) || !json_is_string(target_value)) {
            return false;
        }

        const char *actual_str = json_string_value(actual_value);
        const char *target_str = json_string_value(target_value);

        if (!actual_str || !target_str) {
            return false;
        }

        if (strcmp(operator_str, "EQ") == 0) return strcmp(actual_str, target_str) == 0;
        if (strcmp(operator_str, "NE") == 0) return strcmp(actual_str, target_str) != 0;
        if (strcmp(operator_str, "CONTAINS") == 0) return strstr(actual_str, target_str) != NULL;
        if (strcmp(operator_str, "STARTS_WITH") == 0) return strncmp(actual_str, target_str, strlen(target_str)) == 0;
        if (strcmp(operator_str, "ENDS_WITH") == 0) {
            size_t actual_len = strlen(actual_str);
            size_t target_len = strlen(target_str);
            if (target_len > actual_len) return false;
            return strcmp(actual_str + actual_len - target_len, target_str) == 0;
        }
    }
    else if (strcmp(value_type, "bool") == 0) {
        if (!json_is_boolean(actual_value) || !json_is_boolean(target_value)) {
            return false;
        }

        bool actual = json_boolean_value(actual_value);
        bool target = json_boolean_value(target_value);

        if (strcmp(operator_str, "EQ") == 0) return actual == target;
        if (strcmp(operator_str, "NE") == 0) return actual != target;
    }

    return false;
}

// 执行控制动作
static int execute_control_action(scene_manager_t *manager, json_t *action) {
    if (!manager || !action || !json_is_object(action)) {
        return ERROR_INVALID_PARAM;
    }

    const char *node = json_string_value(json_object_get(action, "node"));
    const char *group = json_string_value(json_object_get(action, "group"));
    const char *tag = json_string_value(json_object_get(action, "tag"));
    json_t *value = json_object_get(action, "value");

    if (!node || !group || !tag || !value) {
        LOG_ERROR("Missing required control action parameters");
        return ERROR_INVALID_PARAM;
    }

    // 创建控制请求
    control_request_t control_request;
    memset(&control_request, 0, sizeof(control_request_t));
    control_request.node = strdup(node);
    control_request.group = strdup(group);
    control_request.tag = strdup(tag);
    control_request.value = json_deep_copy(value);

    // 执行控制（这里需要访问设备管理器，简化实现）
    LOG_INFO("Executing control action: node=%s, group=%s, tag=%s", node, group, tag);

    // 清理请求
    free(control_request.node);
    free(control_request.group);
    free(control_request.tag);
    json_decref(control_request.value);

    return SUCCESS;
}

// 执行通知动作
static int execute_notification_action(scene_manager_t *manager, json_t *action) {
    if (!manager || !action || !json_is_object(action)) {
        return ERROR_INVALID_PARAM;
    }

    const char *title = json_string_value(json_object_get(action, "title"));
    const char *message = json_string_value(json_object_get(action, "message"));
    const char *method = json_string_value(json_object_get(action, "method"));

    LOG_INFO("Executing notification action: %s - %s (method: %s)",
             title ? title : "No title",
             message ? message : "No message",
             method ? method : "unknown");

    // 这里可以实现具体的通知逻辑
    // 例如：发送邮件、短信、推送等

    return SUCCESS;
}

// 场景执行回调函数
static void scene_execution_callback(control_context_t *context, control_response_t *response) {
    // 场景执行完成处理
    // 简化实现
}

// 执行场景动作
static int execute_scene_actions(scene_manager_t *manager, scene_t *scene, const char *trigger_source) {
    if (!manager || !scene) {
        return ERROR_INVALID_PARAM;
    }

    // 检查时间管理
    if (!scene_manager_check_effective_time(scene)) {
        LOG_INFO("Scene '%s' is not in effective time, skipping execution", scene->name);
        return SUCCESS;
    }

    // 更新场景状态
    pthread_rwlock_wrlock(&manager->rwlock);
    scene->status = SCENE_STATUS_EXECUTING;
    scene->last_triggered = time(NULL);
    pthread_rwlock_unlock(&manager->rwlock);

    int result = SUCCESS;
    size_t action_count = json_array_size(scene->actions);

    // 记录执行开始
    time_t start_time = time(NULL);

    for (size_t i = 0; i < action_count; i++) {
        json_t *action = json_array_get(scene->actions, i);
        if (!action || !json_is_object(action)) {
            continue;
        }

        if (scene->action_type == ACTION_TYPE_CONTROL) {
            // 执行控制动作
            int action_result = execute_control_action(manager, action);
            if (action_result != SUCCESS) {
                result = action_result;
                LOG_ERROR("Failed to execute control action %zu for scene '%s'", i, scene->name);
            }
        } else if (scene->action_type == ACTION_TYPE_NOTIFICATION) {
            // 执行通知动作
            int action_result = execute_notification_action(manager, action);
            if (action_result != SUCCESS) {
                result = action_result;
                LOG_ERROR("Failed to execute notification action %zu for scene '%s'", i, scene->name);
            }
        }
    }

    // 更新场景状态
    pthread_rwlock_wrlock(&manager->rwlock);
    if (result == SUCCESS) {
        scene->status = SCENE_STATUS_COMPLETED;
        scene->last_executed = time(NULL);
        scene->execution_count++;
        LOG_INFO("Scene '%s' executed successfully", scene->name);
    } else {
        scene->status = SCENE_STATUS_FAILED;
        LOG_ERROR("Scene '%s' execution failed", scene->name);
    }
    pthread_rwlock_unlock(&manager->rwlock);

    // 记录执行历史到数据库
    if (manager->db_mgr) {
        json_t *executed_actions = json_array();
        for (size_t i = 0; i < action_count; i++) {
            json_t *action = json_array_get(scene->actions, i);
            if (action) {
                json_array_append_new(executed_actions, json_deep_copy(action));
            }
        }

        char *executed_actions_str = json_dumps(executed_actions, JSON_COMPACT);
        json_decref(executed_actions);

        // 构建执行历史记录（简化实现）
        char sql[1024];
        snprintf(sql, sizeof(sql),
                 "INSERT INTO scene_execution_history (scene_id, scene_name, trigger_mode, trigger_source, action_type, status, start_time, end_time, executed_actions) "
                 "VALUES (%d, '%s', %d, '%s', %d, %d, %ld, %ld, '%s')",
                 scene->id, scene->name, scene->trigger_mode, trigger_source,
                 scene->action_type, (result == SUCCESS ? 0 : 1),
                 start_time, time(NULL), executed_actions_str ? executed_actions_str : "[]");

        db_manager_execute(manager->db_mgr, sql, NULL, NULL);

        if (executed_actions_str) {
            free(executed_actions_str);
        }
    }

    // 发送场景执行事件
    scene_event_data_t *event_data = malloc(sizeof(scene_event_data_t));
    if (event_data) {
        event_data->scene_id = scene->id;
        event_data->scene_name = strdup(scene->name);
        event_data->trigger_mode = scene->trigger_mode;
        event_data->action_type = scene->action_type;
        event_data->event_type = (result == SUCCESS) ? EVENT_SCENE_EXECUTED : EVENT_SCENE_FAILED;

        event_data->additional_data = json_object();
        json_object_set_new(event_data->additional_data, "trigger_source", json_string(trigger_source));
        json_object_set_new(event_data->additional_data, "execution_count", json_integer(scene->execution_count));
        json_object_set_new(event_data->additional_data, "action_count", json_integer(action_count));

        event_t *event = event_create(EVENT_SCENE_STATUS_CHANGED, event_data,
                                      sizeof(scene_event_data_t), NULL);
        if (event) {
            event_loop_send_event(manager->event_loop, event);
            event_destroy(event);
        }
    }

    return result;
}

// 定时触发回调函数
static void timer_trigger_callback(void *arg) {
    int scene_id = *(int *)arg;
    // 这里需要通过某种方式获取scene_manager_t实例
    // 简化实现：使用全局变量或通过其他方式传递
}

int scene_manager_init(scene_manager_t *manager, db_manager_t *db_mgr,
                       event_loop_t *event_loop, timer_manager_t *timer,
                       data_pool_t *data_pool) {
    if (!manager || !db_mgr || !event_loop || !timer || !data_pool) {
        return ERROR_INVALID_PARAM;
    }

    memset(manager, 0, sizeof(scene_manager_t));

    if (pthread_rwlock_init(&manager->rwlock, NULL) != 0) {
        return ERROR_THREAD_CREATE;
    }

    manager->db_mgr = db_mgr;
    manager->event_loop = event_loop;
    manager->timer = timer;
    manager->data_pool = data_pool;
    manager->scenes = NULL;

    // 从数据库加载场景
    int result = scene_manager_load_scenes(manager);
    if (result == SUCCESS) {
        manager->initialized = true;
        LOG_INFO("Scene manager initialized successfully");
    }

    return result;
}

int scene_manager_load_scenes(scene_manager_t *manager) {
    if (!manager || !manager->db_mgr) {
        return ERROR_INVALID_PARAM;
    }

    const char *sql = "SELECT id, name, type, description, enabled, trigger_mode, "
                      "trigger_condition, action_type, actions, time_management, "
                      "effective_time, notification_method, notification_config "
                      "FROM scenes WHERE enabled = 1;";

    struct load_context {
        scene_manager_t *manager;
        int count;
    } context = {manager, 0};

    int callback(void *user_data, int argc, char **argv, char **col_names) {
        struct load_context *ctx = (struct load_context *)user_data;

        scene_t *scene = scene_create();
        if (!scene) {
            return 0;
        }

        // 解析数据库字段
        scene->id = atoi(argv[0]);
        scene->name = strdup(argv[1]);
        scene->type = argv[2] ? strdup(argv[2]) : NULL;
        scene->description = argv[3] ? strdup(argv[3]) : NULL;
        scene->enabled = (atoi(argv[4]) == 1);
        scene->trigger_mode = (trigger_mode_t)atoi(argv[5]);
        scene->action_type = (action_type_t)atoi(argv[6]);
        scene->time_management = (atoi(argv[9]) == 1);
        scene->notification_method = argv[11] ? strdup(argv[11]) : NULL;
        scene->notification_config = argv[12] ? strdup(argv[12]) : NULL;

        // 解析触发条件
        if (argv[7]) {
            json_error_t error;
            scene->trigger_condition = json_loads(argv[7], 0, &error);
            if (!scene->trigger_condition) {
                LOG_WARN("Failed to parse trigger condition for scene '%s': %s",
                         scene->name, error.text);
            }
        }

        // 解析执行动作
        if (argv[8]) {
            json_error_t error;
            scene->actions = json_loads(argv[8], 0, &error);
            if (!scene->actions) {
                LOG_WARN("Failed to parse actions for scene '%s': %s",
                         scene->name, error.text);
            }
        }

        // 解析生效时间
        if (argv[10] && scene->time_management) {
            json_error_t error;
            json_t *effective_time_json = json_loads(argv[10], 0, &error);
            if (effective_time_json) {
                parse_effective_time(effective_time_json, &scene->effective_time);
                json_decref(effective_time_json);
            }
        }

        // 添加到场景链表
        pthread_rwlock_wrlock(&ctx->manager->rwlock);
        scene->next = ctx->manager->scenes;
        ctx->manager->scenes = scene;
        ctx->count++;
        pthread_rwlock_unlock(&ctx->manager->rwlock);

        return 0;
    }

    int rc = db_manager_execute(manager->db_mgr, sql, callback, &context);
    if (rc == SUCCESS) {
        LOG_INFO("Loaded %d scenes from database", context.count);

        // 设置定时触发场景
        scene_manager_setup_timer_triggers(manager);
    }

    return rc;
}

int scene_manager_check_value_triggers(scene_manager_t *manager, const char *data_key, json_t *new_value) {
    if (!manager || !data_key || !new_value) {
        return ERROR_INVALID_PARAM;
    }

    pthread_rwlock_rdlock(&manager->rwlock);

    scene_t *scene = manager->scenes;
    int triggered_count = 0;

    while (scene) {
        if (scene->enabled && scene->trigger_mode == TRIGGER_MODE_LINKAGE) {
            // 检查触发条件
            if (scene->trigger_condition && json_is_array(scene->trigger_condition)) {
                size_t condition_count = json_array_size(scene->trigger_condition);
                bool conditions_met = true;

                for (size_t i = 0; i < condition_count; i++) {
                    json_t *condition = json_array_get(scene->trigger_condition, i);
                    if (!condition || !json_is_object(condition)) {
                        conditions_met = false;
                        break;
                    }

                    const char *condition_data_key = json_string_value(json_object_get(condition, "data_key"));
                    if (!condition_data_key || strcmp(condition_data_key, data_key) != 0) {
                        continue; // 这个条件不监控这个数据键
                    }

                    if (!check_value_condition(new_value, condition)) {
                        conditions_met = false;
                        break;
                    }
                }

                if (conditions_met) {
                    LOG_INFO("Value trigger condition met for scene '%s' (ID: %d)",
                             scene->name, scene->id);

                    // 触发场景执行
                    if (execute_scene_actions(manager, scene, "value_trigger") == SUCCESS) {
                        triggered_count++;
                    }
                }
            }
        }
        scene = scene->next;
    }

    pthread_rwlock_unlock(&manager->rwlock);

    if (triggered_count > 0) {
        LOG_INFO("Value triggers: %d scene(s) triggered by data key '%s'", triggered_count, data_key);
    }

    return SUCCESS;
}

int scene_manager_trigger_scene(scene_manager_t *manager, int scene_id, const char *trigger_source) {
    if (!manager || !trigger_source) {
        return ERROR_INVALID_PARAM;
    }

    pthread_rwlock_rdlock(&manager->rwlock);

    scene_t *scene = manager->scenes;
    while (scene) {
        if (scene->id == scene_id && scene->enabled) {
            break;
        }
        scene = scene->next;
    }

    if (!scene) {
        pthread_rwlock_unlock(&manager->rwlock);
        LOG_ERROR("Scene with ID %d not found or not enabled", scene_id);
        return ERROR_INVALID_PARAM;
    }

    // 复制场景指针以便在锁外使用
    scene_t *scene_copy = scene;
    pthread_rwlock_unlock(&manager->rwlock);

    // 检查触发方式
    if (scene_copy->trigger_mode != TRIGGER_MODE_MANUAL) {
        LOG_WARN("Scene '%s' (ID: %d) is not configured for manual triggering",
                 scene_copy->name, scene_id);
        return ERROR_INVALID_PARAM;
    }

    // 执行场景
    int result = execute_scene_actions(manager, scene_copy, trigger_source);
    if (result == SUCCESS) {
        LOG_INFO("Manually triggered scene '%s' (ID: %d) from source: %s",
                 scene_copy->name, scene_id, trigger_source);
    }

    return result;
}

scene_t *scene_create(void) {
    scene_t *scene = malloc(sizeof(scene_t));
    if (!scene) {
        return NULL;
    }

    memset(scene, 0, sizeof(scene_t));
    scene->status = SCENE_STATUS_INACTIVE;
    scene->enabled = true;
    scene->execution_count = 0;
    scene->last_triggered = 0;
    scene->last_executed = 0;
    scene->next = NULL;

    return scene;
}

void scene_free(scene_t *scene) {
    if (!scene) {
        return;
    }

    if (scene->name) free(scene->name);
    if (scene->type) free(scene->type);
    if (scene->description) free(scene->description);
    if (scene->notification_method) free(scene->notification_method);
    if (scene->notification_config) free(scene->notification_config);

    if (scene->trigger_condition) json_decref(scene->trigger_condition);
    if (scene->actions) json_decref(scene->actions);

    free_effective_time(&scene->effective_time);

    free(scene);
}

void scene_manager_destroy(scene_manager_t *manager) {
    if (!manager) {
        return;
    }

    pthread_rwlock_wrlock(&manager->rwlock);

    scene_t *scene = manager->scenes;
    while (scene) {
        scene_t *next = scene->next;
        scene_free(scene);
        scene = next;
    }

    manager->scenes = NULL;
    pthread_rwlock_unlock(&manager->rwlock);
    pthread_rwlock_destroy(&manager->rwlock);

    manager->initialized = false;
}

const char *trigger_mode_to_string(trigger_mode_t mode) {
    switch (mode) {
    case TRIGGER_MODE_TIMER: return "定时";
    case TRIGGER_MODE_LINKAGE: return "联动";
    case TRIGGER_MODE_MANUAL: return "手动";
    default: return "未知";
    }
}

const char *action_type_to_string(action_type_t type) {
    switch (type) {
    case ACTION_TYPE_CONTROL: return "控制点";
    case ACTION_TYPE_NOTIFICATION: return "仅通知";
    default: return "未知";
    }
}
